#include "StompedReality/Asset/AssetManager.h"
#include "StompedReality/Components/BaseComponents.h"
#include "StompedReality/Core.h"
#include "StompedReality/Core/ComponentConstuctionHelper.h"
#include "StompedReality/Core/FileSystem.h"
#include "StompedReality/Core/Game.h"
#include "StompedReality/Core/Graphics/RenderSystem.h"
#include "StompedReality/Core/Input/InputSystem.h"
#include "StompedReality/Core/Logger.h"
#include "StompedReality/Core/Memory/ObjectPoolManager.h"
#include "StompedReality/Core/MessageSystem/MessageSystem.h"
#include "StompedReality/Core/OS/SystemMessageProcessor.h"
#include "StompedReality/Core/Task/TaskManager.h"
#include <assert.h>
namespace StompedReality
{
Game::Game( )
{
  this->m_ComponentSystem = 0;
  this->m_InputSystem = 0;
  this->m_MessageSystem = 0;
  this->m_RenderSystem = 0;
  this->m_Initialized = 0;
  this->m_TaskManager = 0;
  this->m_GameTime = new StompedReality::GameTime( );
  this->m_GameTime->resetTime( );
  this->m_SystemMsgProcessor = 0;
  this->m_FileSystem = 0;
  this->m_AssetManager = 0;
}

Game::~Game( )
{
  delete this->m_ComponentSystem;
  delete this->m_InputSystem;
  delete this->m_MessageSystem;
  delete this->m_GameTime;
  delete this->m_TaskManager;
  delete this->m_SystemMsgProcessor;
  delete this->m_FileSystem;
  delete this->m_AssetManager;
  delete this->m_RenderSystem;
}

bool Game::IsInitialized( )
{
  return this->m_Initialized;
}

StompedReality::GameTime* Game::getGameTime( ) {
  return this->m_GameTime;
}

StompedReality::Core::ComponentObjectPool* Game::getComponentSystem( )
{
  return this->m_ComponentSystem;
}

StompedReality::Asset::AssetManager* Game::getAssetManager( )
{
  return this->m_AssetManager;
}

StompedReality::Graphics::RenderSystem* Game::RenderSystem( )
{
  return this->m_RenderSystem;
}

void Game::setRenderer( StompedReality::Graphics::RenderSystem* render ) {
  this->m_RenderSystem = render;
  this->m_RenderSystem->SetGame( this );
}

StompedReality::Core::MessageSystem* Game::MessageSystem( )
{
  return this->m_MessageSystem;
}

StompedReality::Input::InputSystem* Game::InputSystem( )
{
  return this->m_InputSystem;
}

StompedReality::Core::SystemMessageProcessor* Game::getSysMsgProcessor( )
{
  return this->m_SystemMsgProcessor;
}

StompedReality::Utility::FileSystem* Game::getFileSystem( )
{
  return this->m_FileSystem;
}

void Game::loop( )
{
  LogCallFunctionInfo( "Game", "loop" );
  LogCallFunctionSubInfo( "start loop" );

  while ( this->m_SystemMsgProcessor->Update( ) && this->m_RenderSystem->IsWindowOpen( ) )
  {
    this->m_TaskManager->process( this );
  }

  LogCallFunctionInfo( "Game", "loop" );
  LogCallFunctionSubInfo( "end loop" );
}

bool Game::ParseConfig ( const char* fileName )
{
  this->m_FileSystem = new StompedReality::Utility::FileSystem( );
  assert( this->m_FileSystem != 0 );
  assert( this->m_RenderSystem != 0 );

  //Json::Value root = StompedReality::serialization::JsonHelper::createFromFile ( fileName );
  JsonPTR rootPTR = this->m_FileSystem->openAsJson( fileName );

  this->m_Initialized = true;

  this->m_MessageSystem = new StompedReality::Core::MessageSystem( );
  this->m_MessageSystem->SetGame( this );
  this->m_Initialized &= m_RenderSystem->ParseConfig ( rootPTR );
  assert ( this->m_Initialized == true );

  this->m_ComponentSystem = new StompedReality::Core::ComponentObjectPool( );
  this->m_ComponentSystem->SetGame( this );
  this->m_Initialized &= m_ComponentSystem->ParseConfig ( rootPTR );
  assert ( this->m_Initialized == true );

  this->m_SystemMsgProcessor =  new StompedReality::Core::SystemMessageProcessor( );
  this->m_SystemMsgProcessor->SetGame( this );
  this->m_SystemMsgProcessor->Initialize( );

  this->m_InputSystem = new StompedReality::Input::InputSystem( );
  this->m_InputSystem->SetGame ( this );
  this->m_Initialized &= this->m_InputSystem->ParseConfig( rootPTR );
  assert ( this->m_Initialized == true );

  this->m_TaskManager = new StompedReality::Core::TaskManager( );
  this->m_Initialized &= this->m_TaskManager->ParseConfig( rootPTR );
  assert ( this->m_Initialized == true );

  this->m_AssetManager = new StompedReality::Asset::AssetManager( );
  this->m_AssetManager->SetGame( this );
  this->m_AssetManager->InitSubSystems( );
  this->m_AssetManager->ParseConfig( rootPTR );

  assert( this->m_ComponentSystem != 0 );
  assert( this->m_MessageSystem != 0 );
  assert( this->m_RenderSystem != 0 );

  return this->m_Initialized;
}

void Game::LoadObjects ( Json::Value itemList )
{
  for ( unsigned int i = 0; i < itemList.size( ); ++i )
  {
    this->LoadObject( itemList.get( i, "" ).asCString( ) );
  }
}

void Game::LoadObject( const char* file )
{
  JsonPTR json = this->m_FileSystem->openAsJson( file );
  StompedReality::Core::ComponentConstuctionHelper helper( json );
  helper.SetGame( this );
  helper.CreateComponents ( );
}

}
